/**
 * URL 工具函数
 */

/**
 * 获取 URL 中的查询参数
 * @param {string} name - 参数名
 * @param {string} [url=window.location.href] - URL 字符串，默认为当前页面 URL
 * @returns {string|null} 参数值，如果不存在则返回 null
 */
export function getUrlParam(name, url = window.location.href) {
  name = name.replace(/[[\]]/g, '\\$&');
  const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
  const results = regex.exec(url);
  if (!results) return null;
  if (!results[2]) return '';
  return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

/**
 * 获取 URL 中的所有查询参数
 * @param {string} [url=window.location.href] - URL 字符串，默认为当前页面 URL
 * @returns {Object} 包含所有参数的对象
 */
export function getAllUrlParams(url = window.location.href) {

  if (typeof url !== 'string') {
    return {};
  }

  const queryString = url.split('?')[1] || '';
  const params = {};

  if (!queryString || typeof queryString !== 'string') {
    return params;
  }

  const queryArr = queryString.split('#')[0].split('&');

  for (let i = 0; i < queryArr.length; i++) {
    const pair = typeof queryArr[i] === 'string' ? queryArr[i].split('=') : [];
    const key = pair[0] ? decodeURIComponent(pair[0]) : '';

    // 跳过空键
    if (!key) continue;

    const value = pair[1] === undefined ? '' : decodeURIComponent(pair[1]);

    // 如果已经有这个参数，则转为数组
    if (params[key]) {
      if (Array.isArray(params[key])) {
        params[key].push(value);
      } else {
        params[key] = [params[key], value];
      }
    } else {
      params[key] = value;
    }
  }

  return params;
}

/**
 * 向 URL 添加查询参数
 * @param {string} url - 原始 URL
 * @param {Object|string} param - 要添加的参数，可以是对象或字符串
 * @param {string} [value] - 如果 param 是字符串，则为对应的值
 * @returns {string} 添加参数后的 URL
 */
export function addUrlParam(url, param, value) {
  if (!url) return '';

  let newUrl = url;
  const hashIndex = newUrl.indexOf('#');
  let hash = '';

  if (hashIndex !== -1) {
    hash = newUrl.substring(hashIndex);
    newUrl = newUrl.substring(0, hashIndex);
  }

  const isParamObj = typeof param === 'object';

  if (isParamObj) {
    const keys = Object.keys(param);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      const val = param[key];
      if (val === undefined || val === null) continue;

      const separator = newUrl.indexOf('?') !== -1 ? '&' : '?';
      newUrl += `${separator}${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
    }
  } else {
    const separator = newUrl.indexOf('?') !== -1 ? '&' : '?';
    newUrl += `${separator}${encodeURIComponent(param)}=${encodeURIComponent(value)}`;
  }

  return newUrl + hash;
}

/**
 * 从 URL 中移除指定参数
 * @param {string} url - 原始 URL
 * @param {string|Array} param - 要移除的参数名或参数名数组
 * @returns {string} 移除参数后的 URL
 */
export function removeUrlParam(url, param) {
  if (!url || typeof url !== 'string') return '';

  let newUrl = url;
  const hashIndex = newUrl.indexOf('#');
  let hash = '';

  if (hashIndex !== -1) {
    hash = newUrl.substring(hashIndex);
    newUrl = newUrl.substring(0, hashIndex);
  }

  const questionIndex = newUrl.indexOf('?');
  if (questionIndex === -1) {
    return newUrl + hash;
  }

  const baseUrl = newUrl.substring(0, questionIndex);
  let queryString = newUrl.substring(questionIndex + 1);
  const params = queryString.split('&');
  const paramsToRemove = Array.isArray(param) ? param : [param];

  const filteredParams = params.filter(p => {
    if (typeof p !== 'string') return true;
    const paramName = p.split('=')[0];
    return !paramsToRemove.includes(paramName);
  });

  if (filteredParams.length > 0) {
    return baseUrl + '?' + filteredParams.join('&') + hash;
  }

  return baseUrl + hash;
}

/**
 * 解析 URL 为各个组成部分
 * @param {string} [url=window.location.href] - 要解析的 URL
 * @returns {Object} 包含 URL 各部分的对象
 */
export function parseUrl(url = window.location.href) {
  const parser = document.createElement('a');
  parser.href = url;

  return {
    protocol: parser.protocol, // 协议，如 "http:"
    host: parser.host,         // 主机名和端口，如 "example.com:80"
    hostname: parser.hostname, // 主机名，如 "example.com"
    port: parser.port,         // 端口，如 "80"
    pathname: parser.pathname, // 路径，如 "/path/page.html"
    search: parser.search,     // 查询字符串，如 "?param=value"
    hash: parser.hash,         // 锚点，如 "#section"
    origin: parser.origin,     // 源，如 "http://example.com"
    params: getAllUrlParams(url) // 所有查询参数
  };
}

/**
 * 判断 URL 是否为绝对路径
 * @param {string} url - 要检查的 URL
 * @returns {boolean} 是否为绝对路径
 */
export function isAbsoluteUrl(url) {
  return /^(?:[a-z]+:)?\/\//i.test(url);
}

/**
 * 拼接 URL 路径
 * @param {...string} parts - URL 路径片段
 * @returns {string} 拼接后的 URL
 */
export function joinUrl(...parts) {
  return parts
    .map(part => {
      // 移除开头和结尾的斜杠
      return part.replace(/^\/+|\/+$/g, '');
    })
    .filter(part => part.length > 0)
    .join('/');
}

/**
 * 获取 URL 的基础路径（不包含文件名）
 * @param {string} url - 完整 URL
 * @returns {string} 基础路径
 */
export function getBaseUrl(url) {
  if (!url || typeof url !== 'string') return '';

  // 移除查询字符串和锚点
  const strippedUrl = url.split('?')[0].split('#')[0];

  // 如果 URL 以斜杠结尾，则已经是基础路径
  if (strippedUrl.endsWith('/')) {
    return strippedUrl;
  }

  // 否则移除最后一个路径段
  const lastSlashIndex = strippedUrl.lastIndexOf('/');
  if (lastSlashIndex === -1) {
    return strippedUrl;
  }

  return strippedUrl.substring(0, lastSlashIndex + 1);
}


/**
 * 获取 URL 查询参数并支持类型转换
 * @param {string} name - 参数名
 * @param {*} [defaultValue=null] - 参数不存在时的默认值
 * @param {string} [url=window.location.href] - URL 字符串，默认为当前页面 URL
 * @param {string} [type] - 参数值的目标类型，可选值: 'string', 'number', 'boolean', 'array'
 * @returns {*} 转换后的参数值，如果不存在则返回默认值
 */
export function getQueryParam(name, defaultValue = null, url = window.location.href, type) {
  const value = getUrlParam(name, url);

  if (value === null || value === undefined) {
    return defaultValue;
  }

  // 如果没有指定类型，则返回原始值
  if (!type) {
    return value;
  }

  // 根据指定类型进行转换
  switch (type.toLowerCase()) {
    case 'number':
      const num = Number(value);
      return isNaN(num) ? defaultValue : num;

    case 'boolean':
      return value === 'true' || value === '1' || value === 'yes';

    case 'array':
      // 如果值已经是数组，则直接返回
      if (Array.isArray(value)) {
        return value;
      }
      // 尝试解析 JSON 数组
      try {
        if (value.startsWith('[') && value.endsWith(']')) {
          return JSON.parse(value);
        }
        // 否则按逗号分隔
        return value.split(',').map(item => item.trim());
      } catch (e) {
        return defaultValue;
      }

    case 'string':
    default:
      return String(value);
  }
}

/**
 * 判断当前路径是否与指定路径匹配
 * @param {string|Array<string>} path - 要匹配的路径或路径数组
 * @param {Object} [options] - 配置选项
 * @param {boolean} [options.exact=false] - 是否精确匹配，为 true 时必须完全相同
 * @param {boolean} [options.ignoreParams=true] - 是否忽略查询参数
 * @param {boolean} [options.ignoreHash=true] - 是否忽略哈希部分
 * @param {string} [options.currentPath] - 当前路径，默认为 window.location.pathname
 * @returns {boolean} 是否匹配
 */
export function isActivePath(path, options = {}) {
  const {
    exact = false,
    ignoreParams = true,
    ignoreHash = true,
    currentPath = window.location.pathname
  } = options;

  // 处理路径数组的情况
  if (Array.isArray(path)) {
    return path.some(p => isActivePath(p, options));
  }

  // 获取当前完整 URL
  let currentUrl = currentPath;

  // 如果不忽略查询参数，则加上查询字符串
  if (!ignoreParams) {
    currentUrl = currentUrl + window.location.search;
  }

  // 如果不忽略哈希，则加上哈希部分
  if (!ignoreHash) {
    currentUrl = currentUrl + window.location.hash;
  }

  // 处理路径
  let targetPath = path;

  // 确保路径以 / 开头
  if (!targetPath.startsWith('/')) {
    targetPath = '/' + targetPath;
  }

  // 精确匹配模式
  if (exact) {
    return currentUrl === targetPath;
  }

  // 非精确匹配模式，检查当前路径是否以目标路径开头
  // 或者目标路径是否以当前路径开头
  return currentUrl.startsWith(targetPath) ||
    (targetPath !== '/' && currentUrl === targetPath.replace(/\/$/, ''));
}